#include "SocketHandler.h"

#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#endif
#include <stdlib.h>
#include <errno.h>

#include <sys/time.h>   
#include <unistd.h>   


SocketHandler::SocketHandler() :
	m_maxsock(0)
{
	FD_ZERO(&m_rfds);
	FD_ZERO(&m_wfds);
}

SocketHandler::~SocketHandler() {
	while (m_sockets.size()) {
		fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());
		socket_m::iterator it = m_sockets.begin();
		Socket *p = it -> second;
		if (p) {
			fprintf(stderr, "  fd %d\n", p -> GetSocket());
			p -> Close();
			fprintf(stderr, "  fd closed %d\n", p -> GetSocket());
			delete p;
			p = NULL;
		}
		m_sockets.erase(it);
	}
}


void SocketHandler::Add(Socket * s) {
	SOCKET sockfd = s->GetSocket();
	FD_SET(sockfd, &m_rfds);   
	FD_SET(sockfd, &m_wfds);
	m_sockets[sockfd] = s;
	if(sockfd > m_maxsock) {
		m_maxsock = sockfd;
	}
}


void SocketHandler::Get(SOCKET s,bool& r,bool& w) {
	if (s >= 0) {
		r = FD_ISSET(s, &m_rfds) ? true : false;
		w = FD_ISSET(s, &m_wfds) ? true : false;
	}
}


int SocketHandler::Select(long sec, long usec, SelectMode mode) {
	struct timeval tv;
	tv.tv_sec = sec;
	tv.tv_usec = usec;
	return Select(&tv, mode);
}

int SocketHandler::Select(SelectMode mode) {
	return Select(NULL, mode);
}


int SocketHandler::Select(struct timeval *tsel, SelectMode mode) {
	int n = 0;
	switch (mode) {
	case ReadMode:
		n = select( (int)(m_maxsock + 1), &m_rfds, NULL, NULL, tsel);
		break;
	case WriteMode:
		n = select( (int)(m_maxsock + 1), NULL, &m_wfds, NULL, tsel);
		break;
	case RWMode:
		n = select( (int)(m_maxsock + 1), &m_rfds, &m_wfds, NULL, tsel);
		break;

	}
	n = select( (int)(m_maxsock + 1),&m_rfds, &m_wfds, NULL, tsel);
	return n;
}


void SocketHandler::Remove(Socket * p) {
	for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++) {
		if (it -> second == p)
		{
			FD_CLR(it -> first, &m_rfds );
			FD_CLR(it -> first, &m_wfds );
			m_sockets.erase(it);
			return;
		}
	}
}

